import {
    defineComponent,
    h,
    computed,
    ref,
    getCurrentInstance,
    onUnmounted,
    inject,
    Ref,
} from 'vue';
import { on, off } from '@/utils/domUtils';

import { renderThumbStyle, BAR_MAP } from './util';

export default defineComponent({
    name: 'Bar',

    props: {
        vertical: Boolean,
        size: String,
        move: Number,
    },

    setup(props) {
        const instance = getCurrentInstance();
        const thumb = ref();
        const wrap = inject('scroll-bar-wrap', {} as Ref<Nullable<HTMLElement>>) as any;
        const bar = computed(() => {
            return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];
        });
        const barStore = ref<Recordable>({});
        const cursorDown = ref();
        const clickThumbHandler = (e: any) => {
            // prevent click event of right button
            if (e.ctrlKey || e.button === 2) {
                return;
            }
            startDrag(e);
            barStore.value[bar.value.axis] =
                e.currentTarget[bar.value.offset] -
                (e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]);
        };

        const clickTrackHandler = (e: any) => {
            const offset = Math.abs(
                e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]
            );
            const thumbHalf = thumb.value[bar.value.offset] / 2;
            const thumbPositionPercentage =
                ((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset];

            wrap.value[bar.value.scroll] =
                (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
        };
        const startDrag = (e: any) => {
            e.stopImmediatePropagation();
            cursorDown.value = true;
            on(document, 'mousemove', mouseMoveDocumentHandler);
            on(document, 'mouseup', mouseUpDocumentHandler);
            document.onselectstart = () => false;
        };

        const mouseMoveDocumentHandler = (e: any) => {
            if (cursorDown.value === false) return;
            const prevPage = barStore.value[bar.value.axis];

            if (!prevPage) return;

            const offset =
                (instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) *
                -1;
            const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
            const thumbPositionPercentage =
                ((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset];
            wrap.value[bar.value.scroll] =
                (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
        };

        function mouseUpDocumentHandler() {
            cursorDown.value = false;
            barStore.value[bar.value.axis] = 0;
            off(document, 'mousemove', mouseMoveDocumentHandler);
            document.onselectstart = null;
        }

        onUnmounted(() => {
            off(document, 'mouseup', mouseUpDocumentHandler);
        });

        return () =>
            h(
                'div',
                {
                    class: ['scrollbar__bar', 'is-' + bar.value.key],
                    onMousedown: clickTrackHandler,
                },
                h('div', {
                    ref: thumb,
                    class: 'scrollbar__thumb',
                    onMousedown: clickThumbHandler,
                    style: renderThumbStyle({
                        size: props.size,
                        move: props.move,
                        bar: bar.value,
                    }),
                })
            );
    },
});
